# -*- coding: utf-8 -*-
import datetime
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from google.appengine.api import users
from django.http import HttpResponse, Http404, HttpResponseRedirect
from google.appengine.ext import db
from app2.forms import *
from app2.models import *
from ragendja.dbutils import get_object_or_404
from ragendja.template import render_to_response
from django.contrib.auth.decorators import login_required
from django.contrib.sites.models import Site, RequestSite
from django.utils.translation import ugettext_lazy as _, ugettext as __

from google.appengine.api import memcache
import re

from app1.models import g_blog,Profile
from app1.views import base_values,del_html,get_current_site,now,paginator

cur_app = "app2"
page_num = 20
###
categories_key = "key_all_categories_%s"%cur_app
memtime=3600

###
#base_values = {}
base_values['g_blog'] = g_blog

def get_categories():
    """get all categories"""
    objects = memcache.get(categories_key)
    if objects is None:
        objects = Category.all().order('-entrycount').fetch(200)
        if len(objects)==0:
            newobj = Category(name = "Default Category 1").put()
            newobj = Category(name = "Default Category 2").put()
            objects = Category.all().order('-entrycount').fetch(2)        
        memcache.add(categories_key, objects,memtime)
    base_values['all_categories'] = objects
    return objects

#get_categories()

def gae_ads():
    objects = memcache.get("%s_all_ads_key"%cur_app)
    if objects is None:
        objects = Ads.all().fetch(20)
        if objects:
            pass
        else:
            updata = []
            updata.append(Ads(name = "index_left_top", value = '<img src="/media/tmp/336x280.jpg"/>', description = "index left top Ads,best size is 336x280px"))
            updata.append(Ads(name = "articlelist_top", value = '<img src="/media/tmp/728x90.gif"/>', description = "list top Ads,best size is 728x90px"))
            updata.append(Ads(name = "article_top", value = '<img src="/media/tmp/728x90.gif"/>', description = "article top Ads,best size is 728x90px"))
            db.put(updata)
            objects = updata
        memcache.add("%s_all_ads_key"%cur_app, objects,memtime*3)
    for each in objects:
        base_values['ads_%s'%each.name] = each.value
    return objects    
gae_ads()

def get_newposts():
    men_key = "%s_newposts_key"%cur_app
    objs = memcache.get(men_key)
    if objs is None:
        objs = Entry.all().order('-pub_time').fetch(10)
        memcache.add(men_key, objs, 3600)
    base_values['newpost_list'] = objs
    return objs

def get_lastcomments():
    men_key = "%s_newcomments_key"%cur_app
    objs = memcache.get(men_key)
    if objs is None:
        objs = Comment.all().order('-date').fetch(10)
        memcache.add(men_key, objs, 3600)
    base_values['newcomment_list'] = objs
    return objs

##############
def generate(request, template_name, template_values={}):
    base_values['current_site'] = get_current_site(request)    
    get_categories()
    get_lastcomments()
    #
    base_values.update(template_values)
    return render_to_response(request,"%s/%s"%(cur_app,template_name),base_values)

def index(request):
    newposts = get_newposts()
    return generate(request,'index.html',{'newposts':newposts})

###
def show_article_short(request,keyid):
    if "/" in keyid:
        keyid = keyid.replace("/","")
    try:keyid = int(keyid)
    except:return HttpResponseRedirect(reverse('app2.views.index'))
    return HttpResponseRedirect(reverse('app2.views.show_article', kwargs=dict(keyid=keyid,title=g_blog.title)))

def show_article(request,keyid,title = g_blog.title):
    try:keyid = int(keyid)
    except:return HttpResponseRedirect(reverse('app2.views.index'))
    men_key = "%s_article_post_%d"%(cur_app,keyid)
    obj = memcache.get(men_key)
    if obj is None:
        obj = Entry.get_by_id(keyid)
        memcache.add(men_key, obj, 3600)
    continue_url = ''
    if obj:
        pagination_div = None
        if request.method == 'POST' and request.user.is_authenticated() and not obj.commentclosed:
            cf = CommentForm(request.POST)
            if cf.is_valid():
                cd = cf.clean()#cleaned_data
                comobj = Comment(entry = obj,
                        date = now(),
                        author = request.user,
                        message = cd['message'],
                        pub_ip = request.META['REMOTE_ADDR']
                        )
                comobj.put()
                #return generate(request,'tip.html',{'tip':str(request.user)})
                if comobj.is_saved():
                    userprofile = Profile.get_or_insert(u"key_%s"%str(request.user),author = request.user,displayname = str(request.user).split("@")[0],email = str(request.user))
                    if comobj.key() not in obj.comment_keys:
                        obj.commentcount += 1
                        obj.comment_keys.insert(0,comobj.key())
                        if obj.commentcount >= 999:
                            obj.commentclosed = True
                        obj.put()
                        #
                        memcache.delete("%s_article_post_%d"%(cur_app,obj.key().id()))
                        memcache.delete("%s_article_comment_%d"%(cur_app,obj.key().id()))
                        if obj.commentcount >=10:
                            allpage = (obj.commentcount+1)/10 + 1
                            for p in range(1,allpage+1):
                                memcache.delete("%s_article_comment_%d_page_%d"%(cur_app,obj.key().id(),p))
                        memcache.delete("%s_newcomments_key"%cur_app)
                    #up cate
                    if obj.key() in obj.category.post_keys:
                        if obj.category.post_keys[0] != obj.key():
                            oldpk = obj.category.post_keys
                            obj.category.post_keys.remove(obj.key())
                            obj.category.post_keys.insert(0,obj.key())
                            obj.category.put()
                            if obj.category.entrycount >=page_num:
                                allpage = (obj.category.entrycount+1)/page_num + 1
                                for p in range(1,allpage+1):
                                    if obj.key() in oldpk[page_num*(p-1):page_num*p]:
                                        memcache.delete("%s_category_posts_%d_page_%d"%(cur_app,obj.category.key().id(),p))
                                        if p != 1:
                                            memcache.delete("%s_category_posts_%d_page_%d"%(cur_app,obj.category.key().id(),1))
                        memcache.delete("%s_category_posts_index_%d"%(cur_app,obj.category.key().id()))
                        memcache.delete("%s_category_posts_%d"%(cur_app,obj.category.key().id()))
                        memcache.delete(categories_key)
                    #
                    if g_blog.admin_email:
                        current_site = get_current_site(request)
                        subject = _(u'New comment on your post <%s>')%obj.title
                        sbody = _(u'#Re: %s\n%s\n\nClick here to view it: %s')
                        #
                        tolist = [g_blog.admin_email]
                        toID = request.POST.get('toID','')
                        if toID:
                            try:
                                tocomobj = Comment.get(toID)
                                if tocomobj:
                                    if tocomobj.profile.email:
                                        tolist.append(tocomobj.profile.email)
                            except:
                                tocomobj.message = ' '
                                pass
                            sbody = sbody%(obj.title,tocomobj.message,"http://%s%s#%d"%(current_site.domain,obj.short_url(),comobj.key().id()))
                        else:
                            sbody = sbody%(obj.title,obj.abstract,"http://%s%s#%d"%(current_site.domain,obj.short_url(),comobj.key().id()))
                        #
                        #return generate(request,'tip.html',{'tip':sbody})
                        if str(obj.author):
                            tolist.append(str(obj.author))
                        
                        from django.core.mail import send_mail
                        try:
                            if len(tolist)==1 and g_blog.admin_email == tolist[0]:
                                pass
                            else:
                                send_mail(subject, sbody.encode('utf8'), g_blog.admin_email, tolist)
                        except:pass
                    return HttpResponseRedirect("%s#comments"%obj.get_absolute_url())
        else:
            if request.user.is_authenticated():
                pass
            else:
                continue_url = users.create_login_url(u"%s#postcomment"%obj.get_absolute_url())
            cf = CommentForm()
        ###
        if obj.commentcount >10:
            page = request.GET.get('page', 1)
            try:page = int(page)
            except:page == 1
            pdic = paginator(page,obj.commentcount)
            men_key = "%s_article_comment_%d_page_%d"%(cur_app,obj.key().id(),page)
            commentlist = memcache.get(men_key)
            if commentlist is None:
                commentlist = db.get(obj.comment_keys[pdic['from']:pdic['to']])
                memcache.add(men_key, commentlist, 3600)
            pagination_div = pdic['pagination_div']            
        else:
            commentlist = obj.comments            
        return generate(request,'detail.html',{'obj':obj,'continue_url':continue_url,'form':cf,'commentlist':commentlist,'pagination_div':pagination_div})
    else:
        return HttpResponseRedirect(reverse('app2.views.index'))

@login_required
def add_article(request,key):
    cateobj = Category.get(key)
    if not cateobj:
        return HttpResponseRedirect(reverse('app2.views.index'))
    if request.method == 'POST':
        ef = EntryForm(request.POST)
        if ef.is_valid():
            cd = ef.cleaned_data
            title = cd['title'].strip()
            if not title:
                return generate(request,'tip.html',{'tip':"title is required."})
            content = del_html(cd['content']).strip()
            if len(content)<10:
                return generate(request,'tip.html',{'tip':"Content is too short."})
            obj = Entry(author = request.user,
                title = title,
                category = cateobj,
                content = cd['content'].replace("<p>&nbsp;</p>",""),
                commentclosed = cd['commentclosed'],
                pub_time = now(),
                pub_ip = request.META['REMOTE_ADDR'])
            obj.put()
            if obj.is_saved():
                #Category
                if obj.key() not in cateobj.post_keys:
                    cateobj.post_keys.insert(0,obj.key())
                    if cateobj.entrycount >= 999:
                        cateobj.post_keys = cateobj.post_keys[:999]
                    cateobj.entrycount = len(cateobj.post_keys)
                    cateobj.put()
                #removecache
                memcache.delete("%s_rsslatest_men_%s"%(cur_app,get_current_site(request).domain))
                memcache.delete("%s_newposts_key"%cur_app)
                memcache.delete("%s_category_posts_index_%d"%(cur_app,obj.category.key().id()))
                memcache.delete("%s_category_posts_%d"%(cur_app,obj.category.key().id()))
                memcache.delete(categories_key)
                if cateobj.entrycount >=page_num:
                    allpage = (cateobj.entrycount+1)/page_num + 1
                    for p in range(1,allpage+1):
                        memcache.delete("%s_category_posts_%d_page_%d"%(cur_app,cateobj.key().id(),p))
            return HttpResponseRedirect(reverse('app2.views.show_article', kwargs=dict(keyid=obj.key().id(),title=obj.title)))
    else:
        ef = EntryForm()
    return generate(request,'add_article.html',{'obj':None,'cateobj':cateobj,'form':ef})

@login_required
def edit_article(request,key):
    obj = Entry.get(key)
    if not obj:
        return generate(request,'tip.html',{'tip':"your request object not exist."})
    if obj.author != request.user:
        if not request.user.is_superuser:
            HttpResponseRedirect(reverse('app2.views.index'))
    
    if request.method == 'POST':
        ef = EntryForm(request.POST)
        if ef.is_valid():
            cd = ef.cleaned_data
            obj.title = cd['title'].strip()
            obj.content = cd['content'].replace("<p>&nbsp;</p>","")
            obj.commentclosed = cd['commentclosed']
            obj.edit_time.append(now()) 
            obj.put()
            if obj.is_saved():
                #removecache
                #Category#obj
                memcache.delete("%s_newposts_key"%cur_app)
                memcache.delete("%s_category_posts_index_%d"%(cur_app,obj.category.key().id()))
                memcache.delete("%s_category_posts_%d"%(cur_app,obj.category.key().id()))
                if obj.category.entrycount >=page_num:
                    allpage = (obj.category.entrycount+1)/page_num + 1
                    for p in range(1,allpage+1):
                        memcache.delete("%s_category_posts_%d_page_%d"%(cur_app,obj.category.key().id(),p))
                memcache.delete("%s_article_post_%d"%(cur_app,obj.key().id()))
            return HttpResponseRedirect(reverse('app2.views.show_article', kwargs=dict(keyid=obj.key().id(),title=obj.title)))
    else:
        ef = EntryForm(instance=obj)
    return generate(request,'add_article.html',{'form':ef})

@login_required
def del_article(request,key):
    obj = Entry.get(key)
    if not obj:
        return generate(request,'tip.html',{'tip':"your request object not exist."})
    if obj.author != request.user:
        if not request.user.is_superuser:
            HttpResponseRedirect(reverse('app2.views.index'))
    if request.method == 'POST':
        #Category
        if obj.key() in obj.category.post_keys:
            obj.category.post_keys.remove(obj.key())
            obj.category.entrycount -= 1
            obj.category.put()
        #comments
        if obj.comment_keys:
            db.delete(obj.comment_keys)
            memcache.delete("%s_newcomments_key"%cur_app)
        #removecache
        memcache.delete("%s_newposts_key"%cur_app)
        memcache.delete("%s_category_posts_index_%d"%(cur_app,obj.category.key().id()))
        memcache.delete("%s_category_posts_%d"%(cur_app,obj.category.key().id()))
        if obj.category.entrycount >=(page_num-1):
            allpage = (obj.category.entrycount+1)/(page_num-1) + 1
            for p in range(1,allpage+1):
                memcache.delete("%s_category_posts_%d_page_%d"%(cur_app,obj.category.key().id(),p))
        memcache.delete("%s_article_post_%d"%(cur_app,obj.key().id()))
        #
        obj.delete()
        return generate(request,'tip.html',{'tip':"your object has been deleted."})
    else:
        return generate(request,'delete_article.html',{'obj':obj})

def category_article(request,keyid,name):
    try:keyid = int(keyid)
    except:return HttpResponseRedirect(reverse('app2.views.index'))
    obj = Category.get_by_id(keyid)
    if obj:
        pagination_div = None
        if obj.entrycount >page_num:
            page = request.GET.get('page', 1)
            try:page = int(page)
            except:page = 1
            pdic = paginator(page,obj.entrycount,page_num = page_num)
            if page == 1:
                cur_articlelist = obj.posts
            else:
                men_key = "%s_category_posts_%d_page_%d"%(cur_app,obj.key().id(),page)
                cur_articlelist = memcache.get(men_key)
                if cur_articlelist is None:
                    cur_articlelist = db.get(obj.post_keys[pdic['from']:pdic['to']])
                    memcache.add(men_key, cur_articlelist, 3600)
            pagination_div = pdic['pagination_div']            
        else:
            cur_articlelist = obj.posts
        return generate(request,'articlelist.html',{'obj':obj,'cur_articlelist':cur_articlelist,'pagination_div':pagination_div})        
    else:
        return HttpResponseRedirect(reverse('app2.views.index'))

@login_required
def myarticles(request):
    cur_articlelist = request.user.user_bbs_posts.order("-pub_time")[:20]
    return generate(request,'myarticlelist.html',{'cur_articlelist':cur_articlelist})

def del_comment(request,key):
    if request.user.is_superuser :
        obj = Comment.get(key)
        if obj:
            if obj.key() in obj.entry.comment_keys:
                obj.entry.comment_keys.remove(obj.key())
                obj.entry.commentcount -= 1
                obj.entry.put()
                memcache.delete("%s_article_comment_%d"%(cur_app,obj.entry.key().id()))
                memcache.delete("%s_article_post_%d"%(cur_app,obj.entry.key().id()))
                if obj.entry.commentcount >=9:
                    allpage = (obj.entry.commentcount+1)/10 + 1
                    for p in range(1,allpage+1):
                        memcache.delete("%s_article_comment_%d_page_%d"%(cur_app,obj.entry.key().id(),p))
                obj.delete()
                memcache.delete("%s_newcomments_key"%cur_app,)
            return generate(request,'tip.html',{'tip':"your object has been deleted."})
        else:
            return generate(request,'tip.html',{'tip':"your request object not exist."})
    else:
        return generate(request,'tip.html',{'tip':u'You do not have permission to operate.'})

def getsitemapxml(request,cate_list):
    current_site = get_current_site(request)
        
    # get from mem
    sitemap = memcache.get("%s_sitemap_men_%s"%(cur_app,current_site.domain))
    #sitemap = None
    if sitemap:
        return sitemap
    #
    urls = []
    #
    loc = "http://%s%s"%(current_site.domain,reverse('app2.views.index'))
    lastmod = "%s"%(now().strftime('%Y-%m-%dT%X+00:00'))
    changefreq = 'always'
    priority = '1.0'
    urlstr = "<url>\n<loc>%s</loc>\n<lastmod>%s</lastmod>\n<changefreq>%s</changefreq>\n<priority>%s</priority>\n</url>\n"%(loc,lastmod,changefreq,priority)
    urls.append(urlstr)   
    #
    
    for cate in cate_list:
        ##get cate
        loc = u"http://%s%s" % (current_site.domain,cate.get_absolute_url())
        lastmod = "%s"%(now().strftime('%Y-%m-%dT%X+00:00'))
        changefreq = 'daily'
        priority = '0.6'
        urlstr = "<url>\n<loc>%s</loc>\n<lastmod>%s</lastmod>\n<changefreq>%s</changefreq>\n<priority>%s</priority>\n</url>\n"%(loc,lastmod,changefreq,priority)
        urls.append(urlstr)
        ##get cate art
        cate_arts = cate.posts_index
        for art in cate_arts:
            loc = u"http://%s%s" % (current_site.domain,art.get_absolute_url())
            lastmod = "%s"%(art.pub_time.strftime('%Y-%m-%dT%X+00:00'))
            changefreq = 'daily'
            priority = '0.5'
            urlstr = "<url>\n<loc>%s</loc>\n<lastmod>%s</lastmod>\n<changefreq>%s</changefreq>\n<priority>%s</priority>\n</url>\n"%(loc,lastmod,changefreq,priority)
            urls.append(urlstr)
    #####
    sitemap = ''.join(urls)
    memcache.add("%s_sitemap_men_%s"%(cur_app,current_site.domain), sitemap, 3600*3)#3h
    return sitemap

def sitemap(request):
    cate_list = get_categories()    
    xmlbody = getsitemapxml(request,cate_list)
    return render_to_response(request,'sitemap.xml',{'xml':xmlbody})

def rsslatest(request):
    current_site = get_current_site(request)
    # get from mem
    xmlbody = memcache.get("%s_rsslatest_men_%s"%(cur_app,current_site.domain))
    #sitemap = None
    if xmlbody:
        return HttpResponse(xmlbody,content_type='application/rss+xml')
    
    baseurl = "http://%s"%current_site.domain
    site_name = g_blog.title
    now_time = now().strftime('%a, %d %b %Y %H:%M:%S GMT')
    subtitle = site_name
    feedurl = "rss.xml"
    
    xml_list = []
    xml_list.append(u'<?xml version="1.0" encoding="UTF-8"?> \n<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">\n<channel>\n<atom:link href="%s%s" rel="self" type="application/rss+xml" /> \n'%( baseurl, reverse('app2.views.rsslatest')))
    xml_list.append(u' xmlns:atom="http://www.w3.org/2005/Atom"')
    head_str = u'<title>%s</title> \n<link>%s</link> \n<description>%s Latest Articles</description> \n<language>en-us</language> \n<copyright>Copyright (C) %s. All rights reserved.</copyright> \n<pubDate>%s</pubDate> \n<lastBuildDate>%s</lastBuildDate>\n<generator>%s RSS Generator</generator> \n'%(site_name,baseurl,site_name,current_site.domain,now_time,now_time,current_site.domain)
    xml_list.append(head_str)
    
    for art in get_newposts():
        art_time = art.pub_time.strftime('%a, %d %b %Y %H:%M:%S GMT')
        art_url = "%s%s"%(baseurl,art.get_absolute_url())
        tmp_str = u'<item> \n<title> %s </title> \n<link>%s</link> \n<guid>%s</guid> \n<description><![CDATA[%s [...<a href="%s" target="_blank">More</a>...]]]></description> \n<category>%s</category> \n<author>%s(%s)</author> \n<pubDate>%s</pubDate>  \n</item> \n'%(art.title, art_url, art_url, art.abstract, art_url, art.category.name, art.profile.displayname,art.profile.displayname, art_time)
        xml_list.append(tmp_str)        
    xml_list.append(u'</channel>\n</rss>\n')
    xmlbody = ''.join(xml_list)
    memcache.add("%s_rsslatest_men_%s"%(cur_app,current_site.domain), xmlbody, 3600*3)#3h
    
    return HttpResponse(xmlbody,content_type='application/rss+xml')
